#include "vsMLDelegate.h"
#include "vsMLModel.h"
#include "vsGlobal.h"

#include <QListView>
#include <QPainter>
#include <QApplication>
#include <QLineEdit>
#include <QRegExpValidator>


vsMLDelegate::vsMLDelegate(QListView *lv, vsMLModel *m) :
    QStyledItemDelegate(lv), owner(lv), model(m)
{
    assert(owner != 0);
    assert(model != 0);

    owner->setItemDelegate(this);

    editor = new QLineEdit(owner);
    editor->setAlignment(Qt::AlignCenter);
    editor->setFocusPolicy(Qt::StrongFocus);
    editor->setAutoFillBackground(true);
    editor->setVisible(false);

    editor->setValidator(new QRegExpValidator(
        QRegExp(QString("[0-9a-z_]{1,%1}").arg(c_vctb_id_max_length)), this));

    connect(editor, &QLineEdit::editingFinished, [this](){ emit commitData(editor); });
}

vsMLDelegate::~vsMLDelegate()
{
    // delete something?
}

void vsMLDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    if (!(index.row() == -1 || model->sortedHeaders.isEmpty()))
    {
        QStyleOptionViewItemV4 opt = option;
        opt.state = opt.state & (~QStyle::State_HasFocus); // removing annoying dots
        int row = index.row();
        painter->setOpacity(1);
        vsMLRow *r = 0;

        if (model->filtering)
        {
            if (row < model->filteredMatch.size())
                r = model->filteredMatch[row];
            else
            {
                r = model->filteredRest[row - model->filteredMatch.size()];
                painter->setOpacity(0.33);
            }
        }
        else r = model->sortedRows[index.row()];

        int columnOffset = 0;
        int col = 0;

        foreach (vsMLHeader *h, model->sortedHeaders)
        {
            switch (h->type) {
            case mlData::name: case mlData::artist: case mlData::path:
                     opt.displayAlignment = Qt::AlignVCenter | Qt::AlignLeft;   break;
            default: opt.displayAlignment = Qt::AlignVCenter | Qt::AlignCenter; break; }

            opt.features = QStyleOptionViewItemV2::HasDisplay;
            opt.text     = r->values[h->type];
            opt.rect     = option.rect;

            if (model->sortedHeaders.size() > 1)
            {
                opt.rect.moveLeft(opt.rect.x() + columnOffset);
                opt.rect.setWidth(h->width);

                if (col == 0)
                    opt.viewItemPosition = QStyleOptionViewItem::Beginning;
                else if (col == model->sortedHeaders.size() - 1)
                    opt.viewItemPosition = QStyleOptionViewItem::End;
                else
                    opt.viewItemPosition = QStyleOptionViewItem::Middle;
            }
            else    opt.viewItemPosition = QStyleOptionViewItem::OnlyOne;

            owner->style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter, owner);

            columnOffset += h->width;
            ++col;
        }
    }
}

QWidget* vsMLDelegate::createEditor(QWidget*, const QStyleOptionViewItem&, const QModelIndex&) const
{
    editor->clear();
    editor->setVisible(true);

    return editor;
}

void vsMLDelegate::destroyEditor(QWidget*, const QModelIndex&) const
{
    editor->clear();
    editor->releaseKeyboard();
    editor->releaseMouse();
    editor->setVisible(false);

    owner->setFocus();
}

void vsMLDelegate::setEditorData(QWidget*, const QModelIndex &i) const
{
    if (i.isValid() && i.row() < model->sortedRows.length())
        editor->setText(model->sortedRows[i.row()]->values[mlData::id]);
}

void vsMLDelegate::setModelData (QWidget*, QAbstractItemModel*, const QModelIndex &i) const
{   // if not an empty or same id, emit a signal to notify gui first, than it'll change model and redraw
    if (i.isValid() && i.row() < model->sortedRows.length())
    {
        const QString &newID = editor->text();
        const QString &oldID = model->sortedRows[i.row()]->values[mlData::id];

        if (!(newID.isEmpty() || newID == oldID))
            emit idSet(oldID, newID);
    }
}

void vsMLDelegate::updateEditorGeometry(QWidget*, const QStyleOptionViewItem &o, const QModelIndex&) const
{
    QRect r = o.rect;

    if (model->mappedHeaders.contains(getTypeStringForMLType(mlData::id)))
    {
        int offset = 0;
        auto hIt = model->sortedHeaders.begin();

        while (hIt != model->sortedHeaders.end())
        {
            if ((*hIt)->type == mlData::id)
                break;
            else
                offset += (*hIt)->width;

            ++hIt;
        }

        assert(hIt != model->sortedHeaders.end()); // should never happen
        r.setLeft(r.left() + offset);
        r.setWidth(model->mappedHeaders[getTypeStringForMLType(mlData::id)]->width);
    }
    else
        r.setWidth(300);

    editor->setGeometry(r);
}
